#ifndef __LINEFLAGS_H__
#define __LINEFLAGS_H__

#include "base/LineMask.h"
#include "util/Logger.h"
#include "util/Pool.h"

class LineFlags {
  private:
    // this is the tag and the index (offset zeroed out)
    VA const _addr;
    uint const _blockSize;

    bool _dirty;

  protected:
    LineMask mask;
    uint64 valids;

  public:
    // overloaded to force use of CALLOC/FREE
    NEW_DELETE_OPERATORS_H(LineFlags,NoSuper);

    LineFlags (VA const addr_,
               uint const blockSize_)
        : _addr(addr_),
          _blockSize(blockSize_),
          _dirty(false),
          valids(0LL)
    { 
    }

    virtual ~LineFlags () {
    }

    // Prototype pattern
    virtual LineFlags* newInstance (VA const addr_) const {
        ASSERT(typeid(*this) == typeid(LineFlags));
        return NEW LineFlags(addr_, getBlockSize());
    }

    LineFlags* clone () {        
        LineFlags* Cloneflag = newInstance(getAddress());
        copyState(Cloneflag);
        return Cloneflag;
    }

    virtual void copyState (LineFlags* _flag) {
        _flag->setValid(this->isValid());
        _flag->setDirty(this->isDirty());
    }
    
    virtual void clearSpeculativeState () {
    }

    virtual bool hasSpeculativeState () const {
        return false;
    }

    virtual bool hasAdditionalMetadata () const {
        return hasSpeculativeState();
    }

  
    VA getAddress () const { 
        return _addr;
    }

    uint getBlockSize () const { 
        return _blockSize;
    }

    virtual bool isValid () const {
        return valids != 0;
    }

    virtual void setValid (bool const newValid) {
        if (newValid) {
            valids = (uint64)(-1LL);
        } else {
            valids = 0LL;
        }
    }

    virtual LineMask& getValidMask () {
        if (isValid()) {
            mask = LineMask::ALL_TRUE;
        } else {
            mask = LineMask::ALL_FALSE;
        }
        return mask;
    }


    bool isDirty () const {
        return _dirty;
    }

    void setDirty (bool const newDirty) {
        _dirty = newDirty;
    }

    virtual LineMask& getDirtyMask () {
        if (isDirty()) {
            mask = LineMask::ALL_TRUE;
        } else {
            mask = LineMask::ALL_FALSE;
        }
        return mask;
    }

  private:
    // LineFlags uses inheritance, so operator= and operator==
    // are unlikely to be used correctly.  We declare them private
    // but never declare a body, which prevents their use.
    LineFlags const & operator= (LineFlags const & rhs);
    bool operator== (LineFlags const & rhs) const;

    char str_buffer[64];

  public:
    char const * str () const;

    virtual bool ltFunctor(LineFlags* y);
    virtual bool eqFunctor(LineFlags* y);

  protected:
    // Returns the number of characters that would have been printed
    // had avail been large enough, not including the trailing '\0'.
    virtual int appendStrForm(char * buf, int avail) const;
};

class LineFlagsAddrLessThan {
  public:
    bool operator() (LineFlags* x, LineFlags* y) {
        return x->getAddress() < y->getAddress();
    }
};

class LineFlagsAddrEquals {
  public:
    bool operator() (LineFlags* x, LineFlags* y) {
        return x->getAddress() == y->getAddress();
    }
};

#endif // __LINEFLAGS_H__
